package com.wens.baselibrary.util

import android.view.View
import com.jakewharton.rxbinding4.view.clicks
import com.jakewharton.rxbinding4.view.longClicks
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.ObservableTransformer
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import java.util.*
import java.util.concurrent.TimeUnit


object RxUtil {
    private val disposables = HashMap<Class<*>, ArrayList<Disposable>>()
    private const val clickInterval = 500

    fun <T> ioToMainTransformer(): ObservableTransformer<T, T> {
        return ObservableTransformer<T, T> {
            it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
        }
    }

    fun <T> mainToIoTransformer(): ObservableTransformer<T, T> {
        return ObservableTransformer<T, T> {
            it.observeOn(Schedulers.io()).subscribeOn(AndroidSchedulers.mainThread())
        }
    }

    fun <T> mainToComputationTransformer(): ObservableTransformer<T, T> {
        return ObservableTransformer<T, T> {
            it.observeOn(Schedulers.computation()).subscribeOn(AndroidSchedulers.mainThread())
        }
    }

    fun <T> computationToMainTransformer(): ObservableTransformer<T, T> {
        return ObservableTransformer<T, T> {
            it.subscribeOn(Schedulers.computation()).observeOn(AndroidSchedulers.mainThread())
        }
    }


    fun clicks(view: View, milliSeconds: Int): Observable<Unit> {
        return view.clicks().throttleFirst(milliSeconds.toLong(), TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
    }

    fun longClicks(view: View, milliSeconds: Int): Observable<Unit> {
        return view.longClicks().throttleFirst(milliSeconds.toLong(), TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
    }

    fun setOnClickListener(view: View, onClickListener: View.OnClickListener?) {
        setOnClickListener(view, onClickListener, clickInterval)
    }

    @Synchronized
    fun setOnClickListener(view: View, onClickListener: View.OnClickListener?, milliSeconds: Int) {
        val subscribe = clicks(view, milliSeconds).subscribe {
            onClickListener?.onClick(
                view
            )
        }
        addDisposable(view, subscribe)
    }

    @Synchronized
    fun addDisposable(view: View, disposable: Disposable) {
        addDisposable(view.context.javaClass, disposable)
    }

    @Synchronized
    fun addDisposable(contextClass: Class<*>, disposable: Disposable) {
        if (!disposables.containsKey(contextClass)) disposables[contextClass] = ArrayList()
        val disposableArrayList = disposables[contextClass]
        disposableArrayList?.add(disposable)
    }

    @Synchronized
    fun dispose(key: Class<*>) {
        if (disposables.containsKey(key)) {
            val disposableArrayList = disposables[key]
            if (disposableArrayList != null) {
                for (disposable in disposableArrayList) {
                    if (!disposable.isDisposed) disposable.dispose()
                }
            }
            disposables.remove(key)
        }
    }
}